home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sndhrdw / wiping.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  6KB  |  264 lines

  1. /***************************************************************************
  2.  
  3.     NAMCO sound driver.
  4.  
  5.     This driver handles the three known types of NAMCO wavetable sounds:
  6.  
  7.         - 3-voice mono (Pac-Man, Pengo, Dig Dug, etc)
  8.         - 8-voice mono (Mappy, Dig Dug 2, etc)
  9.         - 8-voice stereo (System 1)
  10.  
  11. ***************************************************************************/
  12.  
  13. #include "driver.h"
  14.  
  15.  
  16. /* 8 voices max */
  17. #define MAX_VOICES 8
  18.  
  19.  
  20. const int samplerate = 48000;
  21. const int defgain = 48;
  22.  
  23.  
  24. /* this structure defines the parameters for a channel */
  25. typedef struct
  26. {
  27.     int frequency;
  28.     int counter;
  29.     int volume[2];
  30.     const unsigned char *wave;
  31.     int oneshot;
  32.     int oneshotplaying;
  33. } sound_channel;
  34.  
  35.  
  36. /* globals available to everyone */
  37. unsigned char *wiping_soundregs;
  38. unsigned char *wiping_wavedata;
  39.  
  40. /* data about the sound system */
  41. static sound_channel channel_list[MAX_VOICES];
  42. static sound_channel *last_channel;
  43.  
  44. /* global sound parameters */
  45. static const unsigned char *sound_prom,*sound_rom;
  46. static int num_voices;
  47. static int sound_enable;
  48. static int stream;
  49.  
  50. /* mixer tables and internal buffers */
  51. static INT16 *mixer_table;
  52. static INT16 *mixer_lookup;
  53. static short *mixer_buffer;
  54. static short *mixer_buffer_2;
  55.  
  56.  
  57.  
  58. /* build a table to divide by the number of voices; gain is specified as gain*16 */
  59. static int make_mixer_table(int voices, int gain)
  60. {
  61.     int count = voices * 128;
  62.     int i;
  63.  
  64.     /* allocate memory */
  65.     mixer_table = malloc(256 * voices * sizeof(INT16));
  66.     if (!mixer_table)
  67.         return 1;
  68.  
  69.     /* find the middle of the table */
  70.     mixer_lookup = mixer_table + (128 * voices);
  71.  
  72.     /* fill in the table - 16 bit case */
  73.     for (i = 0; i < count; i++)
  74.     {
  75.         int val = i * gain * 16 / voices;
  76.         if (val > 32767) val = 32767;
  77.         mixer_lookup[ i] = val;
  78.         mixer_lookup[-i] = -val;
  79.     }
  80.  
  81.     return 0;
  82. }
  83.  
  84.  
  85. /* generate sound to the mix buffer in mono */
  86. static void wiping_update_mono(int ch, INT16 *buffer, int length)
  87. {
  88.     sound_channel *voice;
  89.     short *mix;
  90.     int i;
  91.  
  92.     /* if no sound, we're done */
  93.     if (sound_enable == 0)
  94.     {
  95.         memset(buffer, 0, length * 2);
  96.         return;
  97.     }
  98.  
  99.     /* zap the contents of the mixer buffer */
  100.     memset(mixer_buffer, 0, length * sizeof(short));
  101.  
  102.     /* loop over each voice and add its contribution */
  103.     for (voice = channel_list; voice < last_channel; voice++)
  104.     {
  105.         int f = 16*voice->frequency;
  106.         int v = voice->volume[0];
  107.  
  108.         /* only update if we have non-zero volume and frequency */
  109.         if (v && f)
  110.         {
  111.             const unsigned char *w = voice->wave;
  112.             int c = voice->counter;
  113.  
  114.             mix = mixer_buffer;
  115.  
  116.             /* add our contribution */
  117.             for (i = 0; i < length; i++)
  118.             {
  119.                 int offs;
  120.  
  121.                 c += f;
  122.  
  123.                 if (voice->oneshot)
  124.                 {
  125.                     if (voice->oneshotplaying)
  126.                     {
  127.                         offs = (c >> 15);
  128.                         if (w[offs>>1] == 0xff)
  129.                         {
  130.                             voice->oneshotplaying = 0;
  131.                         }
  132.  
  133.                         if (voice->oneshotplaying)
  134.                         {
  135.                             /* use full byte, first the high 4 bits, then the low 4 bits */
  136.                             if (offs & 1)
  137.                                 *mix++ += ((w[offs>>1] & 0x0f) - 8) * v;
  138.                             else
  139.                                 *mix++ += (((w[offs>>1]>>4) & 0x0f) - 8) * v;
  140.                         }
  141.                     }
  142.                 }
  143.                 else
  144.                 {
  145.                     offs = (c >> 15) & 0x1f;
  146.  
  147.                     /* use full byte, first the high 4 bits, then the low 4 bits */
  148.                     if (offs & 1)
  149.                         *mix++ += ((w[offs>>1] & 0x0f) - 8) * v;
  150.                     else
  151.                         *mix++ += (((w[offs>>1]>>4) & 0x0f) - 8) * v;
  152.                 }
  153.             }
  154.  
  155.             /* update the counter for this voice */
  156.             voice->counter = c;
  157.         }
  158.     }
  159.  
  160.     /* mix it down */
  161.     mix = mixer_buffer;
  162.     for (i = 0; i < length; i++)
  163.         *buffer++ = mixer_lookup[*mix++];
  164. }
  165.  
  166.  
  167.  
  168. int wiping_sh_start(const struct MachineSound *msound)
  169. {
  170.     const char *mono_name = "Wiping";
  171.     sound_channel *voice;
  172.  
  173.     /* get stream channels */
  174.     stream = stream_init(mono_name,100/*intf->volume*/, samplerate, 0, wiping_update_mono);
  175.  
  176.     /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */
  177.     if ((mixer_buffer = malloc(2 * sizeof(short) * samplerate)) == 0)
  178.         return 1;
  179.     mixer_buffer_2 = mixer_buffer + samplerate;
  180.  
  181.     /* build the mixer table */
  182.     if (make_mixer_table(8, defgain))
  183.     {
  184.         free (mixer_buffer);
  185.         return 1;
  186.     }
  187.  
  188.     /* extract globals from the interface */
  189.     num_voices = 8;
  190.     last_channel = channel_list + num_voices;
  191.  
  192.     sound_rom = memory_region(REGION_SOUND1);
  193.     sound_prom = memory_region(REGION_SOUND2);
  194.  
  195.     /* start with sound enabled, many games don't have a sound enable register */
  196.     sound_enable = 1;
  197.  
  198.     /* reset all the voices */
  199.     for (voice = channel_list; voice < last_channel; voice++)
  200.     {
  201.         voice->frequency = 0;
  202.         voice->volume[0] = voice->volume[1] = 0;
  203.         voice->wave = &sound_prom[0];
  204.         voice->counter = 0;
  205.     }
  206.  
  207.     return 0;
  208. }
  209.  
  210.  
  211. void wiping_sh_stop(void)
  212. {
  213.     free (mixer_table);
  214.     free (mixer_buffer);
  215. }
  216.  
  217.  
  218. /********************************************************************************/
  219.  
  220. WRITE_HANDLER( wiping_sound_w )
  221. {
  222.     sound_channel *voice;
  223.     int base;
  224.  
  225.     /* update the streams */
  226.     stream_update(stream, 0);
  227.  
  228.     /* set the register */
  229.     wiping_soundregs[offset] = data;
  230.  
  231.     /* recompute all the voice parameters */
  232.     if (offset <= 0x3f)
  233.     {
  234.         for (base = 0, voice = channel_list; voice < last_channel; voice++, base += 8)
  235.         {
  236.             voice->frequency = wiping_soundregs[0x02 + base] & 0x0f;
  237.             voice->frequency = voice->frequency * 16 + ((wiping_soundregs[0x01 + base]) & 0x0f);
  238.             voice->frequency = voice->frequency * 16 + ((wiping_soundregs[0x00 + base]) & 0x0f);
  239.  
  240.             voice->volume[0] = wiping_soundregs[0x07 + base] & 0x0f;
  241.             if (wiping_soundregs[0x5 + base] & 0x0f)
  242.             {
  243.                 voice->wave = &sound_rom[128 * (16 * (wiping_soundregs[0x5 + base] & 0x0f)
  244.                         + (wiping_soundregs[0x2005 + base] & 0x0f))];
  245.                 voice->oneshot = 1;
  246.             }
  247.             else
  248.             {
  249.                 voice->wave = &sound_rom[16 * (wiping_soundregs[0x3 + base] & 0x0f)];
  250.                 voice->oneshot = 0;
  251.             }
  252.         }
  253.     }
  254.     else if (offset >= 0x2000)
  255.     {
  256.         voice = &channel_list[(offset & 0x3f)/8];
  257.         if (voice->oneshot)
  258.         {
  259.             voice->counter = 0;
  260.             voice->oneshotplaying = 1;
  261.         }
  262.     }
  263. }
  264.